package com.chart.web.controller.chart;

import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.model.CannedAccessControlList;
import com.aliyun.oss.model.PutObjectRequest;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.chart.chart.domian.dto.UserExportDTO;
import com.chart.chart.domian.dto.UserPhotoExportDTO;
import com.chart.chart.service.SysUserExportNewService;
import com.chart.chart.service.SysUserExportService;
import com.chart.common.core.domain.AjaxResult;
import com.chart.common.core.domain.entity.SysUser;
import com.chart.common.core.domain.entity.SysUserExport;
import com.chart.common.core.domain.entity.SysUserExportNew;
import com.chart.common.core.domain.entity.UserCoinLog;
import com.chart.common.utils.FileUtils;
import com.chart.common.utils.SecurityUtils;
import com.chart.common.utils.uuid.IdUtils;
import com.chart.framework.config.OssConfig;
import com.chart.system.service.ISysUserService;
import com.chart.system.service.IUserCoinLogsService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import javax.imageio.*;
import javax.imageio.stream.ImageInputStream;
import javax.imageio.stream.ImageOutputStream;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.List;

/**
 * 导出
 *
 * @author 罗继全
 * 2024/9/26 16:39
 */
@Slf4j
@RestController
@RequestMapping("")
public class SysUserExportController {

    @Autowired
    private SysUserExportService sysUserExportService;
    @Autowired
    private SysUserExportNewService sysUserExportNewService;

    @Autowired
    private OssConfig ossConfig;

    @Autowired
    private ISysUserService userService;
    @Autowired
    private IUserCoinLogsService userCoinLogsService;
    /**
     * 图片保存接口
     *
     * @param userExportDTO
     * @return
     * @throws IllegalStateException
     * @throws IOException
     */

    @PostMapping("/userExport/saveUserExport")
    public AjaxResult saveUserExport(@RequestBody UserExportDTO userExportDTO) throws IllegalStateException, IOException {
        String fileBase64 = userExportDTO.getFileBase64();
        Long userId = userExportDTO.getUserId();
        // 验证 Base64 字符串和用户ID
        if (fileBase64 == null || fileBase64.isEmpty()) {
            return AjaxResult.error("文件内容为空");
        }
        if (userId == null) {
            return AjaxResult.error("用户userId为空");
        }

        // 去掉 Base64 前缀（如果存在），例如 "data:image/png;base64,"
        String base64Prefix = "base64,";
        int base64Index = fileBase64.indexOf(base64Prefix);
        if (base64Index != -1) {
            fileBase64 = fileBase64.substring(base64Index + base64Prefix.length());
        }

        // 解码 Base64 字符串为字节数组
        byte[] decodedBytes;
        try {
            decodedBytes = Base64.getDecoder().decode(fileBase64);
        } catch (IllegalArgumentException e) {
            return AjaxResult.error("Base64 格式不正确");
        }

        // 文件保存路径
        //String realPath = "D:/附件/userExport";
        String realPath = "/data/dev/public/userExport";

        // 或 "/data/dev/public/userExport"
        // 如果文件夹不存在，创建它
        FileUtils.createDirectory(realPath);

        // 文件名可以根据时间戳或用户ID生成，避免重名
        String fileName = userId + System.currentTimeMillis() + ".png";  // 根据需求修改扩展名
        String filePath = realPath + "/" + fileName;

        // 将解码后的字节数组保存为文件
        try (FileOutputStream fos = new FileOutputStream(filePath)) {
            fos.write(decodedBytes);
        } catch (IOException e) {
            return AjaxResult.error("文件保存失败");
        }

        // 生成保存路径的URL
        String urls = "/static/userExport" + "/" + fileName;

        // 创建 SysUserExport 对象并保存
        SysUserExport sysUserExport = new SysUserExport();
        sysUserExport.setImageUrl(urls);
        sysUserExport.setUserId(userId);

        // 保存数据并返回结果
        boolean save = sysUserExportService.save(sysUserExport);
        if (save) {
            return AjaxResult.success(urls);  // 保存成功时返回 URL
        } else {
            return AjaxResult.error("保存失败");  // 保存失败时返回错误信息
        }
    }


    /**
     * 下载照片
     * @param
     * @return
     */

    @PostMapping("/userExport/deductCoins")
    public AjaxResult deductAiCoins(Integer coins, String type) {
        Long userId = SecurityUtils.getUserId();
        Integer totalCoins = userCoinLogsService.getTotalCoinsByUserId(userId);
        if (coins == 0) {
// 构建返回数据
            Map<String, Object> data = new HashMap<>();
            data.put("deductAiCoins", coins);
            data.put("totalCoins", totalCoins);
            data.put("deductStatus", 0);
            return AjaxResult.success("操作成功", data);
        }
        if (totalCoins - coins < 0) {
// 构建返回数据
            Map<String, Object> data = new HashMap<>();
            data.put("deductAiCoins", 0);
            data.put("totalCoins", totalCoins);
            data.put("deductStatus", 1);
            return AjaxResult.success("金币不足", data);
        } else {
// 扣除金币
            UserCoinLog log = new UserCoinLog();
            log.setUserId(userId);
            log.setAction(type);
            log.setCoins(-coins); // 扣除金币数，使用负值表示扣除
            log.setCreatedAt(LocalDateTime.now());
            userCoinLogsService.save(log);


// 构建返回数据
            Map<String, Object> data = new HashMap<>();
            data.put("deductAiCoins", coins);
            data.put("totalCoins", totalCoins);
            data.put("deductStatus", 0);
            return AjaxResult.success("操作成功", data);
        }

    }






    //@PostMapping("saveUserExportNew")
   // @PostMapping("/userExport/saveChartExport")

    /**
     * 导出图片
     * @param userPhotoExportDTO
     * @return
     */
    @PostMapping("/saveChartExport")
    public AjaxResult saveUserExportNew(@RequestBody UserPhotoExportDTO userPhotoExportDTO) {
        Long userId = SecurityUtils.getUserId();
        String fileBase64 = userPhotoExportDTO.getFileBase64();
        String name = userPhotoExportDTO.getName();
        Float quality = userPhotoExportDTO.getQuality();

        SysUser sysUser = userService.queryById(userId);
        Integer isVip = sysUser.getIsVip();

        // 参数校验：确保 quality 有效
        if (quality == null) {
            return AjaxResult.error(400," 'quality' 为空，请重新上传！");
        }
        if (quality <= 0 || quality > 1) {
            return AjaxResult.error(400," 'quality' 在 0 和 1 之间，请选择合适范围！");
        }

        // 定义扣除的金币数
        int deductedCoins = 0;

        // 如果 quality = 1，则检查会员状态
        if (quality == 1.0f) {
            // 如果是非会员
            if (isVip == 0) {
                // 查询用户的金币数量
                Integer totalCoins = userCoinLogsService.getTotalCoinsByUserId(userId);
                if (totalCoins == null || totalCoins < 2) {
                    //return AjaxResult.error("金币不足，无法导出高质量图片！");
                    return  new  AjaxResult(507,"金币不足，无法导出高质量图片！");
                }

                // 扣除 2 个金币，并插入扣除记录
                deductedCoins = 2; // 扣除 2 个金币
                UserCoinLog log = new UserCoinLog();
                log.setUserId(userId);
                log.setAction("baseDeduct");
                log.setCoins(-deductedCoins); // 扣除 2 个金币
                log.setCreatedAt(LocalDateTime.now());
                userCoinLogsService.save(log);
            }
        }

        // 参数校验
        if (fileBase64 == null || fileBase64.isEmpty()) {
            return AjaxResult.error(400,"文件内容为空");
        }
        if (userId == null) {
            return AjaxResult.error("用户 ID 为空");
        }
        if (name == null || name.trim().isEmpty()) {
            return AjaxResult.error(400,"文件名为空");
        }

        // 提取并解码 Base64 数据
        String base64Prefix = "base64,";
        int base64Index = fileBase64.indexOf(base64Prefix);
        if (base64Index != -1) {
            fileBase64 = fileBase64.substring(base64Index + base64Prefix.length());
        }

        byte[] decodedBytes;
        try {
            decodedBytes = Base64.getDecoder().decode(fileBase64);
        } catch (IllegalArgumentException e) {
            log.error("Base64 格式不正确", e);
            return AjaxResult.error("Base64 格式不正确");
        }

        // 根据画质调整文件大小或压缩
        byte[] adjustedBytes = adjustImageQuality(decodedBytes, quality);

        // 获取当前日期并格式化为 "yyMMdd"
        String datePrefix = LocalDate.now().format(DateTimeFormatter.ofPattern("yyMMdd"));

        // 生成随机数字并进行 MD5 加密
        String randomNumber = IdUtils.generateRandomNumber();
        String md5FileName = generateMD5(randomNumber);

        String type = userPhotoExportDTO.getType();
        System.out.println("我是照片类型" + type);

        // 参数校验：确保 type 有效，默认值为 "png"
        if (type == null || type.trim().isEmpty()) {
            type = "png"; // 默认文件类型
        } else {
            type = type.toLowerCase();
        }

        List<String> supportedTypes = Arrays.asList("png", "jpg", "jpeg", "bmp");
        if (!supportedTypes.contains(type)) {
            throw new IllegalArgumentException("不支持的图片格式: " + type);
        }

        String fileName = "userExport/" + datePrefix + "/" + md5FileName + "." + type;

        // 上传文件到 OSS
        String fileUrl;
        OSS ossClient = null;
        try {
            ossClient = new OSSClientBuilder().build(ossConfig.getEndpoint(),
                    ossConfig.getAccessKeyId(), ossConfig.getAccessKeySecret());

            // 上传文件
            ossClient.putObject(ossConfig.getBucketName(), fileName, new ByteArrayInputStream(adjustedBytes));

            // 设置文件权限为公共读
            ossClient.setObjectAcl(ossConfig.getBucketName(), fileName, CannedAccessControlList.PublicRead);

            // 构造文件访问 URL
            if (ossConfig.getCustomDomain() != null && !ossConfig.getCustomDomain().isEmpty()) {
                fileUrl = ossConfig.getCustomDomain() + fileName;
            } else {
                fileUrl = "https://" + ossConfig.getBucketName() + "." + ossConfig.getEndpoint() + "/" + fileName;
            }

        } catch (Exception e) {
            log.error("文件上传到 OSS 失败", e);
            return AjaxResult.error("文件上传失败");
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }


        SysUserExport sysUserExport = new SysUserExport();
        sysUserExport.setImageUrl(fileUrl);
        sysUserExport.setUserId(userId);
        sysUserExport.setName(userPhotoExportDTO.getName());
        boolean isSaved =  sysUserExportService.save(sysUserExport);



        if (!isSaved) {
            return AjaxResult.error("文件记录保存失败");
        }

        // 返回文件访问 URL 和扣除金币数
        Map<String, Object> responseData = new HashMap<>();
        responseData.put("fileUrl", fileUrl);
        responseData.put("deductedCoins", deductedCoins); // 返回扣除的金币数

        return AjaxResult.success(responseData);
    }









    /**
     * 检测图片的格式
     *
     * @param imageBytes 图片字节数据
     * @return 图片格式（如 png, jpg, bmp 等）
     */
    private String detectImageFormat(byte[] imageBytes) {
        try (ByteArrayInputStream inputStream = new ByteArrayInputStream(imageBytes)) {
            ImageInputStream imageStream = ImageIO.createImageInputStream(inputStream);
            Iterator<ImageReader> readers = ImageIO.getImageReaders(imageStream);
            if (readers.hasNext()) {
                return readers.next().getFormatName();
            }
        } catch (IOException e) {
            log.error("无法检测图片格式", e);
        }
        return null;
    }










    // 生成 MD5 值
    private String generateMD5(String input) {
        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            md.update(input.getBytes());
            byte[] digest = md.digest();
            StringBuilder sb = new StringBuilder();
            for (byte b : digest) {
                sb.append(String.format("%02x", b)); // 转换为十六进制字符串
            }
            return sb.toString();
        } catch (NoSuchAlgorithmException e) {
            log.error("MD5 生成失败", e);
            return "";
        }
    }


    /**
     * 根据id查询导出照片列表
     */

    @GetMapping("/userExport/queryUserExportList")
    public AjaxResult queryUserExportList(Long userId) {
        LambdaQueryWrapper<SysUserExport> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SysUserExport::getUserId, userId);
        List<SysUserExport> list = sysUserExportService.list(wrapper);
        return AjaxResult.success(list);
    }



    private byte[] adjustImageQuality(byte[] imageBytes, float quality) {
        try (ByteArrayInputStream inputStream = new ByteArrayInputStream(imageBytes);
             ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {

            // 使用 ImageIO 加载图片
            BufferedImage image = ImageIO.read(inputStream);
            if (image == null) {
                throw new IllegalArgumentException("无法读取图片");
            }

            // 如果质量不是 1，调整图片分辨率（缩放处理）
            if (quality < 1.0f) {
                int newWidth = Math.round(image.getWidth() * quality);
                int newHeight = Math.round(image.getHeight() * quality);
                BufferedImage resizedImage = new BufferedImage(newWidth, newHeight, image.getType());
                Graphics2D g2d = resizedImage.createGraphics();
                g2d.drawImage(image, 0, 0, newWidth, newHeight, null);
                g2d.dispose();
                image = resizedImage; // 替换为缩放后的图片
            }

            // 将图片写入输出流，始终使用 PNG 格式
            ImageIO.write(image, "png", outputStream);

            return outputStream.toByteArray();
        } catch (IOException e) {
            log.error("调整图片画质失败", e);
            throw new RuntimeException("调整图片画质失败", e);
        }
    }

}
